/*! 
  \file compress.c
  \brief Implementation of the main compression program.
*/

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> 

#include <utils.h>
#include <bwt.h>
#include <mtf.h>
#include <huff.h>

#define SIZE 1024

int main(int argc, char **argv) {
  FILE *ifp, *ofp;
  char *input_file, *output_file;
  unsigned char *buffer1, *buffer2;
  unsigned int bytes_read = 0;
  unsigned int bwt_index;
  int status;
  
  if (argc != 3) {
    printf("Usage: %s <input_file> <output_file>\n", argv[0]);
    exit(-1);
  }
  
  input_file = argv[1];
  output_file = argv[2];
  
  if (open_file(input_file, "r", &ifp, 1) == -1)
    exit(-1);
    
  if (open_file(output_file, "w", &ofp, 0) == -1)
    exit(-1);

  struct stat *buf = (struct stat*)malloc(sizeof(struct stat));
  lstat(input_file, buf);
  int size = buf->st_size;
  buffer1 = (unsigned char*)malloc(size);
  buffer2 = (unsigned char*)malloc(size);

  while (bytes_read == 0) {
    bytes_read = fread(buffer1, 1, size, ifp);
    if(bytes_read == 0) break;
    
    if (bytes_read != size) {
      if (ferror(ifp)) {
        printf("An error occurred while reading the input file.\n");
        clearerr(ifp);
        break;
      }
    }
    buffer1[(int)bytes_read] = '\0';
    
      /*Do the Burrows Wheeler encoding, original contents is in buffer1, bw_c
      encoded output is in buffer2.*/
	  status = bw_c((char*)buffer1, bytes_read, (char*)buffer2, (int*)&bwt_index);
	  if (status == -1) {
	    printf("An error occurred while encoding using Burrows-Wheeler.\n");
	    break;
	  }
	  
	  /*Reorder the string using the move-to-front algorithm. bw_c is in buffer2,
	  move-to-front encoded string is stored in buffer1.*/
	  status = mtfencode(buffer1, buffer2, bytes_read);
	  if (status == -1) {
	    printf("An error occurred while encoding using Move-To-Front.\n");
	    break;
	  }

         free(buffer2);
         buffer2 = (unsigned char*)malloc(2*size);

	  /*TODO: Add huffmann encoding, and figure out a way to write/format the
	  output file appropriately so that it includes bw indices, and huffmann
	  data.*/
        int *comp_size = (int*)malloc(sizeof(int));
	  status = huffencode(buffer2, buffer1, (int)bytes_read, comp_size, bwt_index, bytes_read);
	  if (status == -1) {
	    printf("An error occurred while encoding using Huffman Coding.\n");
	    break;
	  }

	  /*Write the encoded string to the output file*/
	  fwrite(buffer2, 1, *comp_size, ofp);

  }
  
  fclose(ifp);
  fclose(ofp);

  return 0;
}

